package cn.comtom.ewbs.signature.controller;

import java.util.List;

import javax.validation.constraints.NotBlank;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import cn.comtom.ewbs.signature.common.enums.BasicError;
import cn.comtom.ewbs.signature.common.vo.response.ApiEntityResponse;
import cn.comtom.ewbs.signature.common.vo.response.ApiListResponse;
import cn.comtom.ewbs.signature.common.vo.response.ApiResponse;
import cn.comtom.ewbs.signature.common.vo.response.ApiResponseBuilder;
import cn.dev33.satoken.annotation.SaCheckSafe;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.basic.SaBasicUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;

@RestController
@RequestMapping("/auth/")
@Api(tags = "认证中心", description = "认证中心")
@Validated
@Slf4j
public class Oauth2Controller {

    /**
     * 登录
     * @param account 账号
     * @param password 密码
     * @param clientType 客户端类型
     * @return 响应结果
     */
    @PostMapping("doLogin")
    @ApiOperation(value = "登录", notes = "登录")
    @SaIgnore //可忽略拦截，免登录访问
    public ApiEntityResponse<SaTokenInfo> doLogin(@NotBlank String account, @NotBlank String password, @NotBlank String clientType,String rememberMe) {
        // 此处仅作模拟示例，真实项目需要从数据库中查询数据进行比对 
        if("zhang".equals(account) && "123456".equals(password)) {
        	StpUtil.login(account, clientType);
        	SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            return ApiEntityResponse.ok(tokenInfo);
        }
        return ApiResponseBuilder.buildEntityError(BasicError.OPT_FALID_VALUE);
    }

    /**
     * 检查是否登录
     * @return 响应结果
     */
    @GetMapping("isLogin")
    @ApiOperation(value = "检查是否登录", notes = "检查是否登录")
    public ApiResponse isLogin() {
    	if(StpUtil.isLogin()) {
    		return ApiResponse.ok();
    	}else {
    		return ApiResponse.error();
    	}
    }
    
    /**
     * 当前账号注销下线
     * @return 响应结果
     */
    @GetMapping("logout")
    @ApiOperation(value = "注销", notes = "注销")
    public ApiResponse logout() {
        StpUtil.logout();
        return ApiResponse.ok();
    }
    
    
    /**
     * 将指定账号踢下线 
     * @param account 账号
     * @return 响应结果
     */
    @PostMapping("kickout")
    @ApiOperation(value = "将指定账号踢下线", notes = "将指定账号踢下线")
    public ApiResponse kickout(@NotBlank String account) {
        StpUtil.kickout(account); 
        return ApiResponse.ok();
    }
    
    /**
     * 封号 指定账号
     * @param account 账号
     * @param time 封禁时间（单位：秒）
     * @return 响应结果
     */
    @PostMapping("disable")
    @ApiOperation(value = "封号", notes = "封号")
    public ApiResponse disable(@NotBlank @RequestParam String account, @RequestParam Long time) {
    	if(time != null) {
    		//封号指定时间,并立即下线
    		StpUtil.disable(account, time);
    		StpUtil.logout(account);
    	}else {
    		//永久封号,并立即下线
    		StpUtil.disable(account, -1);
    		StpUtil.logout(account);
    	}
    	 return ApiResponse.ok();
    }
    
    /**
     * 解封
     * @param account 账号
     * @return 响应结果
     */
    @PostMapping("enable")
    @ApiOperation(value = "解封", notes = "解封")
    public ApiResponse disable(@NotBlank String account) {
    	 // 解除封禁
    	 StpUtil.untieDisable(account); 
    	 return ApiResponse.ok();
    }
    
    /**
     * 获取token信息
     * @return 响应结果
     */
    @GetMapping("getTokenInfo")
    @ApiOperation(value = "获取token信息", notes = "获取token信息")
    public ApiEntityResponse<SaTokenInfo> getTokenInfo() {
    	SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
    	return ApiEntityResponse.ok(tokenInfo);
    }
    
    /**
     * 获取当前用户所有权限列表
     * @return 响应结果
     */
    @GetMapping("getPermissionList")
    @ApiOperation(value = "获取当前用户所有权限列表", notes = "获取当前用户所有权限列表")
    public ApiListResponse<String> getPermissionList() {
    	List<String> permissionList = StpUtil.getPermissionList();
    	return ApiListResponse.ok(permissionList);
    }
    
    /**
     * 获取当前用户所有角色列表
     * @return 响应结果
     */
    @GetMapping("getRoleList")
    @ApiOperation(value = "获取当前用户所有角色列表", notes = "获取当前用户所有角色列表")
    public ApiListResponse<String> getRoleList() {
    	List<String> roleList = StpUtil.getRoleList();
    	return ApiListResponse.ok(roleList);
    }
    
    /**
     * 获取指定用户所有权限列表
     * @param account 账号
     * @return 响应结果
     */
    @GetMapping("getPermissionListByAccount")
    @ApiOperation(value = "获取指定用户所有权限列表", notes = "获取指定用户所有权限列表")
    public ApiListResponse<String> getPermissionListByAccount(@NotBlank String account) {
    	List<String> permissionList = StpUtil.getPermissionList(account);
    	return ApiListResponse.ok(permissionList);
    }
    
    /**
     * 获取指定用户所有角色列表
     * @param account 账号
     * @return 响应结果
     */
    @GetMapping("getRoleListByAccount")
    @ApiOperation(value = "获取指定用户所有角色列表", notes = "获取指定用户所有角色列表")
    public ApiListResponse<String> getRoleListByAccount(@NotBlank String account) {
    	List<String> roleList = StpUtil.getRoleList(account);
    	return ApiListResponse.ok(roleList);
    }
    
    /**
     * 当前账号是否拥有指定角色
     * @param roleCode 角色编码
     * @return 响应结果
     */
    @GetMapping("hasRole")
    @ApiOperation(value = "当前账号是否拥有指定角色", notes = "当前账号是否拥有指定角色")
    public ApiResponse hasRole(@NotBlank String roleCode) {
    	if(StpUtil.hasRole(roleCode)) {
    		return ApiResponse.ok();
    	}
    	return ApiResponse.error();
    }
    
    /**
     * 当前账号是否拥有指定权限
     * @param permissionCode 权限编码
     * @return 响应结果
     */
    @GetMapping("hasPermission")
    @ApiOperation(value = "当前账号是否拥有指定权限", notes = "当前账号是否拥有指定权限")
    public ApiResponse hasPermission(@NotBlank String permissionCode) {
    	if(StpUtil.hasPermission(permissionCode)) {
    		return ApiResponse.ok();
    	}
    	return ApiResponse.error();
    }
    
    /**
     * 指定账号是否拥有指定角色
     * @param roleCode 角色编码
     * @param account 账号
     * @return 响应结果
     */
    @GetMapping("hasRoleByAccount")
    @ApiOperation(value = "指定账号是否拥有指定角色", notes = "指定账号是否拥有指定角色")
    public ApiResponse hasRoleByAccount(@NotBlank String roleCode, @NotBlank String account) {
    	if(StpUtil.hasRole(account, roleCode)) {
    		return ApiResponse.ok();
    	}
    	return ApiResponse.error();
    }
    
    /**
     * 指定账号是否拥有指定权限
     * @param permissionCode 权限编码
     * @param account 账号
     * @return 响应结果
     */
    @GetMapping("hasPermissionByAccount")
    @ApiOperation(value = "指定账号是否拥有指定权限", notes = "指定账号是否拥有指定权限")
    public ApiResponse hasPermissionByAccount(@NotBlank String permissionCode, @NotBlank String account) {
    	if(StpUtil.hasPermission(account, permissionCode)){
    		return ApiResponse.ok();
    	}
    	return ApiResponse.error();
    }
    
    
    /**
     * 当前会话切换到其他账号
     * @param account 账号
     * @return 响应结果
     */
    @PostMapping("switchUser")
    @ApiOperation(value = "当前会话切换到其他账号", notes = "当前会话切换到其他账号")
    public ApiResponse switchUser(@NotBlank String account) {
    	 // 将当前会话[身份临时切换]为其它账号 
        StpUtil.switchTo(account);
        return ApiResponse.ok();
    }
    
    /**
     * 二级认证：必须二级认证之后才能进入该方法
     * @return 响应结果
     */
    @SaCheckSafe      
    @GetMapping("saCheckSafe")
    @ApiOperation(value = "二级认证", notes = "二级认证")
    public ApiResponse saCheckSafe(){

    	return ApiResponse.ok();
    }
    
    /**
     * 该接口启用 Http Basic 认证
     * @return 响应结果
     */
    @GetMapping("httpBasic")
    @ApiOperation(value = "Http Basic 认证", notes = "Http Basic 认证")
    @SaIgnore //可忽略拦截，免登录访问
    public SaResult httpBasic() {
    	// 对当前会话进行 Basic 校验，账号密码为 yml 配置的值（例如：sa-token.basic=sa:123456）
    	SaBasicUtil.check();

    	// 对当前会话进行 Basic 校验，账号密码为：`admin / 123456`
    	//除了访问后再输入账号密码外，我们还可以在 URL 中直接拼接账号密码通过 Basic 认证，例如：
    	//http://admin:1111@127.0.0.1:9800/auth/httpBasic
    	//SaBasicUtil.check("admin:123456");

        return SaResult.ok();
    }
    

}